﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Nb.Common.Configurations
{
    public class XmlDocHelper
    {
        public class ConnectionStringNode
        {
            public string Name { get; set; }
            public string ConnectionString { get; set; }
            public string ProviderName { get; set; }
        }

        public class AppSettingNode
        {
            public string Key { get; set; }
            public string Value { get; set; }
        }

        /// <summary>
        /// 获取ConnectionString值
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="name">连接字符串名字</param>
        /// <returns>连接字符串</returns>
        public static string GetConnectionString(string configPath, string name)
        {
            string value = "";
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);
            string nodePath = "/configuration/connectionStrings/add[@name='" + name + "']";
            var theNode = doc.SelectSingleNode(nodePath);
            if (theNode == null)
            {
                return null;
            }

            if (theNode.Attributes != null)
            {
                value = theNode.Attributes["connectionString"].Value;
            }

            return value;
        }

        /// <summary>
        /// 获取ConnectionString值(批量)
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <returns>连接字符串字典</returns>
        public static IList<ConnectionStringNode> GetConnectionStrings(string configPath)
        {
            IList<ConnectionStringNode> results = new List<ConnectionStringNode>();

            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);
            const string nodePath = @"/configuration/connectionStrings/add";
            XmlNodeList theNodes = doc.SelectNodes(nodePath);
            if (theNodes == null || theNodes.Count == 0)
            {
                return results;
            }

            foreach (XmlNode theNode in theNodes)
            {
                if (theNode.Attributes != null)
                {
                    string name = theNode.Attributes["name"].Value;
                    string connectionString = null;
                    if (theNode.Attributes["connectionString"] != null)
                    {
                        connectionString = theNode.Attributes["connectionString"].Value;
                    }
                    string providerName = null;
                    if (theNode.Attributes["providerName"] != null)
                    {
                        providerName = theNode.Attributes["providerName"].Value;
                    }

                    var node = new ConnectionStringNode()
                    {
                        Name = name,
                        ConnectionString = connectionString,
                        ProviderName = providerName
                    };

                    results.Add(node);
                }
            }
            return results;
        }

        /// <summary>
        /// 设置ConnectionString的某个值
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="name">连接字符串名字</param>
        /// <param name="connectionString">连接字符串值</param>
        /// <param name="providerName">providerName</param>
        /// <returns>值，如果找不到，返回""</returns>
        public static void SetConnectionString(string configPath, string name, string connectionString, string providerName = "System.Data.SqlClient")
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);

            const string settingPath = @"/configuration/connectionStrings";
            var settingNode = doc.SelectSingleNode(settingPath);
            if (settingNode == null)
            {
                throw new ApplicationException("config文件没有找到connectionStrings配置节");
            }

            string addPath = "/configuration/connectionStrings/add[@name='" + name + "']";
            var addNode = doc.SelectSingleNode(addPath);
            if (addNode == null)
            {
                XmlElement addElement = doc.CreateElement("add");
                addElement.SetAttribute("name", name);
                addElement.SetAttribute("connectionString", connectionString);
                addElement.SetAttribute("providerName", providerName);
                settingNode.AppendChild(addElement);
            }
            else
            {
                XmlElement addElement = (XmlElement)addNode;
                addElement.SetAttribute("name", name);
                addElement.SetAttribute("connectionString", connectionString);
                addElement.SetAttribute("providerName", providerName);
            }
            doc.Save(configPath);
        }

        /// <summary>
        /// 删除某个连接字符串
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="name">连接字符串名字</param>
        public static void RemoveConnectionString(string configPath, string name)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);
            string xPath = "/configuration/connectionStrings/add[@name='" + name + "']";
            RemoveXmlNode(configPath, xPath);
        }

        /// <summary>
        /// 获取AppSetting值
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="key">app settting 的键</param>
        /// <returns>值，如果找不到，返回""</returns>
        public static string GetAppSetting(string configPath, string key)
        {
            string value = "";
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);
            string nodePath = "/configuration/appSettings/add[@key='" + key + "']";
            var theNode = doc.SelectSingleNode(nodePath);
            if (theNode == null)
            {
                return null;
            }

            if (theNode.Attributes != null)
            {
                value = theNode.Attributes["value"].Value;
            }

            return value;
        }

        /// <summary>
        /// 获取AppSetting值（批量）
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <returns>字典，如果有key无value，返回的项目value是null</returns>
        public static IList<AppSettingNode> GetAppSettings(string configPath)
        {
            IList<AppSettingNode> results = new List<AppSettingNode>();

            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);
            const string nodePath = @"/configuration/appSettings/add";
            XmlNodeList theNodes = doc.SelectNodes(nodePath);
            if (theNodes == null || theNodes.Count == 0)
            {
                return results;
            }

            foreach (XmlNode theNode in theNodes)
            {
                if (theNode.Attributes != null)
                {
                    string key = theNode.Attributes["key"].Value;
                    string value = null;
                    if (theNode.Attributes["value"] != null)
                    {
                        value = theNode.Attributes["value"].Value;
                    }

                    var node = new AppSettingNode()
                    {
                        Key = key,
                        Value = value
                    };

                    results.Add(node);
                }
            }
            return results;
        }

        /// <summary>
        /// 增加或者修改AppSetting的值
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="key">app settting 的键</param>
        /// <param name="value">app settting 的值</param>
        public static void SetAppSetting(string configPath, string key, string value)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);


            const string appSettingPath = @"/configuration/appSettings";
            var appSettingNode = doc.SelectSingleNode(appSettingPath);
            if (appSettingNode == null)
            {
                throw new ApplicationException("config文件没有找到appSettings配置节");
            }


            string addPath = "/configuration/appSettings/add[@key='" + key + "']";
            var addNode = doc.SelectSingleNode(addPath);
            if (addNode == null)
            {
                XmlElement addElement = doc.CreateElement("add");
                addElement.SetAttribute("key", key);
                addElement.SetAttribute("value", value);
                appSettingNode.AppendChild(addElement);
            }
            else
            {
                XmlElement addElement = (XmlElement)addNode;
                addElement.SetAttribute("key", key);
                addElement.SetAttribute("value", value);
            }

            doc.Save(configPath);
        }

        /// <summary>
        /// 删除某个AppSetting
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="key">app settting 的键</param>
        public static void RemoveAppSetting(string configPath, string key)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);
            string xPath = "/configuration/appSettings/add[@key='" + key + "']";
            RemoveXmlNode(configPath, xPath);
        }

        /// <summary>
        /// 删除某个节点
        /// </summary>
        /// <param name="configPath">配置的路径</param>
        /// <param name="xPath">节点XPath路径</param>
        public static void RemoveXmlNode(string configPath, string xPath)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);

            string addPath = xPath;
            var addNode = doc.SelectSingleNode(addPath);
            if (addNode == null)
            {
                return;
            }
            else
            {
                XmlElement addElement = (XmlElement)addNode;
                if (addElement.ParentNode != null)
                {
                    addElement.ParentNode.RemoveChild(addElement);
                }
            }
            doc.Save(configPath);
        }
    }
}
